import UpmsMenuAndAuthorityResponse from '@/core/upms/types/model/response/UpmsMenuAndAuthorityResponse'
import upmsMenuManager from '@/core/upms/manager/upmsMenuManager'
import permissionManager from '@/core/auth/manager/permissionManager'
import useMenuStore from '@/core/upms/store/useMenuStore'
import UpmsConstants from '@/core/oauth2/constants/UpmsConstants'
import UpmsMenuShowStatusEnum from '@/core/upms/enums/UpmsMenuShowStatusEnum'
import debounceUtils from '@/core/utils/debounceUtils'
import authManager from '@/core/auth/manager/authManager'
import promiseUtils from '@/core/utils/promiseUtils'
import UpmsMenuResponse from '@/core/upms/types/model/response/UpmsMenuResponse'
import upmsMenuAdminServerApi from '@/core/upms/generated/serverapi/admin/upmsMenuAdminServerApi'

class UpmsMenuService {
	getByIdsWithDebounce: (id: string) => Promise<UpmsMenuResponse[]> = debounceUtils.define<string, UpmsMenuResponse[]>(
		(ids: string[]): Promise<UpmsMenuResponse[]> => {
			const userAccessToken = authManager.getAndCheckUserTokenInfo().accessToken
			return promiseUtils.ofResponse(upmsMenuAdminServerApi.getByIds(userAccessToken, ids)).check()
		},
	)

	getAllAdminMenuByCurrentAccount = async (): Promise<UpmsMenuAndAuthorityResponse[]> => {
		return await upmsMenuManager.getAllAdminMenuByCurrentAccount()
	}

	getAllMenuFromStoreOrServerApi = async (): Promise<UpmsMenuAndAuthorityResponse[]> => {
		return await upmsMenuManager.getAllMenuFromStoreOrServerApi()
	}

	getMenus = async (): Promise<UpmsMenuAndAuthorityResponse[]> => {
		const menus = await upmsMenuManager
			.getAllAdminMenuByCurrentAccount()
			.then(menus => {
				useMenuStore.setState({ menus: menus })
				return menus
			})
			.then(this.filterByAuthority)
		return menus
	}

	getMenuBreadcrumbByPath = (pathname: string): UpmsMenuAndAuthorityResponse[] => {
		const menus = useMenuStore.getState().menus
		if (menus.length === 0) {
			return menus
		}
		const findMenu = menus.find(menu => menu.menu.uri === pathname)
		if (!findMenu) {
			return []
		}
		const newMenus = this.getMenuBreadcrumbById(findMenu.menu.id, menus)
		return newMenus
	}

	private getMenuBreadcrumbById = (id: string, menus: UpmsMenuAndAuthorityResponse[]): UpmsMenuAndAuthorityResponse[] => {
		const findMenu = this.getMenuById(id, menus)
		if (!findMenu) {
			return []
		}
		if (findMenu.menu.parentId === UpmsConstants.ROOT_PARENT_ID) {
			return [findMenu]
		}
		const parentMenu = this.getMenuBreadcrumbById(findMenu.menu.parentId, menus)
		return [...parentMenu, findMenu]
	}

	private getMenuById = (id: string, menus: UpmsMenuAndAuthorityResponse[]): UpmsMenuAndAuthorityResponse | undefined => {
		return menus.find(menu => menu.menu.id === id)
	}
	private filterByAuthority = (menus: UpmsMenuAndAuthorityResponse[]): UpmsMenuAndAuthorityResponse[] => {
		return menus.filter(menu => {
			if (menu.menu.showStatus !== UpmsMenuShowStatusEnum.DISPLAY.getCode()) {
				return false
			}
			const menuPermissions = menu?.authority?.key ? [menu.authority.key] : []
			if (menuPermissions.length == 0) {
				return true
			}
			const hasPermission: boolean = permissionManager.hasAny(menuPermissions)
			return hasPermission
		})
	}
}

export default new UpmsMenuService()
